import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { ComponentPropsType } from '../../components/QuestionComponents'
import { produce } from 'immer'
import { getNextSelectedId, insertNewComponent } from './utils'
import { cloneDeep } from 'lodash'
import { nanoid } from 'nanoid'

// 每个组件的信息
export type componentInfoType = {
  // 组件的唯一标识
  _id: string
  // 组件绑定的Key
  name: string
  // 组件的名称
  title: string
  // 组件的类型
  type: string
  // 组件的属性
  props: ComponentPropsType
  // 是否显示
  isHidden?: boolean
  // 是否锁定
  isLock?: boolean
}

export type ComponentsStateType = {
  // 当前选中的id
  selectedId: string
  // 问卷组件列表
  componentsList: Array<componentInfoType>
  // 复制的组件信息
  copiedComponent?: componentInfoType
}

// 数据的默认值
const INIT_STATE: ComponentsStateType = {
  selectedId: '',
  componentsList: [],
  copiedComponent: undefined
}

export const componentsSlice = createSlice({
  name: 'components',
  initialState: INIT_STATE,
  reducers: {
    // 重置所有组件
    resertComponents(
      state: ComponentsStateType,
      action: PayloadAction<ComponentsStateType>
    ) {
      return action.payload
    },
    // 设置当前选中的组件ID
    changeSelectedId: produce(
      (draft: ComponentsStateType, action: PayloadAction<string>) => {
        draft.selectedId = action.payload
      }
    ),
    // 添加组件
    addComponent: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<componentInfoType>
      ) => {
        const newComponent = action.payload
        insertNewComponent(draft, newComponent)
      }
    ),
    // 根据id修改组件属性
    updateComponentProps: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{
          _id: string
          newProps: ComponentPropsType
        }>
      ) => {
        const { _id, newProps } = action.payload
        // 根据id找到对应的属性
        const target = draft.componentsList.find(item => item._id === _id)
        if (target) {
          target.props = newProps
        }
      }
    ),
    // 删除某个题目
    deleteComponent: produce((draft: ComponentsStateType) => {
      // 删除
      const removeIndex = draft.componentsList.findIndex(
        item => item._id === draft.selectedId
      )
      // 自动选中下一个组件
      draft.selectedId = getNextSelectedId(
        draft.selectedId,
        draft.componentsList
      )
      draft.componentsList.splice(removeIndex, 1)
    }),
    // 隐藏某个组件
    hiddenComponent: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{ _id: string; isHidden: boolean }>
      ) => {
        const { _id, isHidden } = action.payload
        const target = draft.componentsList.find(item => item._id === _id)
        if (target) {
          if (isHidden) {
            draft.selectedId = getNextSelectedId(_id, draft.componentsList)
          } else {
            // 显示组件的话，自动选中当前组件
            draft.selectedId = _id
          }
          target.isHidden = isHidden
        }
      }
    ),
    // 切换锁定和解锁
    toogleLock: produce(
      (draft: ComponentsStateType, action: PayloadAction<{ _id: string }>) => {
        const { _id } = action.payload
        const target = draft.componentsList.find(item => item._id === _id)
        if (target) {
          target.isLock = !target.isLock
        }
      }
    ),
    // 复制组件到剪切板
    copyComponent: produce(
      (draft: ComponentsStateType, action: PayloadAction<{ _id: string }>) => {
        // 获取当前的组件
        const { _id } = action.payload
        const target = draft.componentsList.find(item => item._id === _id)
        if (target) {
          // 深拷贝
          draft.copiedComponent = cloneDeep(target)
        }
      }
    ),
    // 粘贴组件到当前选中组件下面
    pasteComponent: produce((draft: ComponentsStateType) => {
      // 更新组件Id
      if (draft.copiedComponent) {
        draft.copiedComponent._id = nanoid()
        insertNewComponent(draft, draft.copiedComponent)
      }
    }),
    // 选中上一个
    selectPrevComponent: produce((draft: ComponentsStateType) => {
      const { selectedId, componentsList } = draft
      const index = componentsList.findIndex(item => item._id === selectedId)
      // 如果已经是第一个了，则return
      if (index <= 0) return
      draft.selectedId = componentsList[index - 1]._id
    }),
    // 选中下一个
    selectNextComponent: produce((draft: ComponentsStateType) => {
      const { selectedId, componentsList } = draft
      const index = componentsList.findIndex(item => item._id === selectedId)
      // 如果已经是最后一个了，则return
      if (index === componentsList.length - 1) return
      draft.selectedId = componentsList[index + 1]._id
    }),
    // 修改组件标题
    changeComponentTitle: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<{
          _id: string
          title: string
        }>
      ) => {
        const { _id, title } = action.payload
        const target = draft.componentsList.find(item => item._id === _id)
        if (target) {
          target.title = title
        }
      }
    ),
    // 获取排序后的组件列表
    reorderComponents: produce(
      (
        draft: ComponentsStateType,
        action: PayloadAction<Array<componentInfoType>>
      ) => {
        draft.componentsList = action.payload
      }
    )
  }
})

export const {
  resertComponents,
  changeSelectedId,
  addComponent,
  updateComponentProps,
  deleteComponent,
  hiddenComponent,
  toogleLock,
  copyComponent,
  pasteComponent,
  selectPrevComponent,
  selectNextComponent,
  changeComponentTitle,
  reorderComponents
} = componentsSlice.actions

// 使用 undoable 包裹 reducer
// export default undoable(componentsSlice.reducer, {
//   // 过滤不需要记录的操作（如选中组件）
//   filter: excludeAction([
//     'componentsSlice/changeSelectedId',
//     'componentsSlice/selectPrevComponent',
//     'componentsSlice/selectNextComponent',
//     'componentsSlice/resertComponents'
//   ]),
//   // 限制历史记录最多 20 步
//   limit: 20,
//   // 自定义undo类型
//   undoType: 'components/UNDO',
//   redoType: 'components/REDO'
// })

export default componentsSlice.reducer
